home *** CD-ROM | disk | FTP | other *** search
/ Aminet 50 / Aminet 50 (2002)(GTI - Schatztruhe)[!][Aug 2002].iso / Aminet / text / edit / tecoc-146.lha / pg.mem < prev    next >
Text File  |  1992-08-24  |  41KB  |  857 lines

  1.  
  2.  
  3.  
  4.                                      TECO-C
  5.  
  6.                                Programmer's Guide
  7.          (last updated February 18, 1991 to reflect TECO-C version 140)
  8.  
  9.  
  10.  
  11. 1  INTRODUCTION
  12.  
  13.      These notes apply to TECOC version  135,  which  runs  under  VAX/VMS,
  14. MS-DOS,  and  Unix  (SunOS,  which  is BSD).  See file AAREADME.TXT for the
  15. specifics of operating system and compilers which have been used.
  16.  
  17.      TECO-C is meant to be a complete implementation of TECO as defined  by
  18. the  Standard  TECO  User's  Guide  and Language Reference Manual, (in file
  19. TECO.DOC).  It was written so that the author could move to  many  machines
  20. without knowing many editors.
  21.  
  22.  
  23.  
  24. 2  COMPILING AND LINKING
  25.  
  26.      Conditional compilation directives are used to build TECO-C  correctly
  27. for   different   environments.    Identifiers   automatically  defined  by
  28. the different compilers are used.  Some identifiers defined in file ZPORT.H
  29. control  whether  video  support  or extra debugging code is included.  See
  30. "VIDEO" and "DEBUGGING". Files are provided which "build" TECO-C in various
  31. environments.  See file AAREADME.TXT for details.
  32.  
  33.  
  34.  
  35. 3  RUNNING TECO-C
  36.  
  37.      When you run TECO, the command line used to invoke TECO is parsed  for
  38. an input/output file name and several optional switches. TECO-11 parses the
  39. command line using a TECO macro imbedded in the program.  TECO-C  does  the
  40. same  thing.   Actually,  the imbedded macro used to parse the command line
  41. was stolen from TECO-11.  I commented it and then  modified  it  to  repair
  42. minor  inconsistencies.   Use  of  TECO-11's  macro makes TECO-C invocation
  43. identical to TECO-11's, even responding to "make love" with "Not war?".
  44.  
  45.      The macro is in file CLPARS.TES.  The compressed version (no  comments
  46. or  whitespace)  is  in  file  CLPARS.TEC.   The  GENCLP  program  converts
  47. CLPARS.TEC into CLPARS.H, an  include  file  suitable  for  compiling  into
  48. TECO-C.
  49.  
  50.  
  51.  
  52. 4  CODE CONVENTIONS
  53.  
  54.      The code is not modular.  Communication between almost  all  functions
  55. is  through  global variables, not argument lists.  There is a reason:  the
  56. nature of the basic parsing algorithm is  to  use  the  characters  in  the
  57. command  string  as indices into a table of functions.  This makes for very
  58. fast command parsing, but it means that all the functions  have  to  modify
  59.  
  60.                                                                 Page 2
  61.  
  62.  
  63. global  values,  because no arguments are passed in.  In other words, there
  64. were going to be 130 or so un-modular functions anyway,  so  I gave  up  on
  65. modularity.  This explanation does not explain some of the complications in
  66. the search code, like the global variable SrcTyp.  Oh, well.
  67.  
  68.      Here's a brief list of some of the conventions followed by the code:
  69.  
  70.      1.  TECO-C is portable, so some  convention  was  needed  to  separate
  71.          portable  code  from  system-dependent  code.   There  is one file
  72.          containing the system-dependent  code  for  each  platform  TECO-C
  73.          supports.   These files have names that start with a "Z":  ZVMS.C,
  74.          ZMSDOS.C and ZUNIX.C.
  75.  
  76.          All the system-dependent functions in those  files  start  with  a
  77.          "Z".   For  example,  the function that allocates memory is called
  78.          ZAlloc.  A VMS version of ZAlloc can be found in  ZVMS.C,  and  an
  79.          MS-DOS version can be found in ZMSDOS.C.
  80.  
  81.          An extra file called ZUNKN.C exists to help efforts to port TECO-C
  82.          to  a  new  environment.   This  file  contains  stubs for all the
  83.          system-dependent functions.
  84.  
  85.      2.  All   system-independent    global    variables    are    declared
  86.          alphabetically  in  file  TECOC.C.   They are defined in DEFEXT.H,
  87.          which is included by all modules.
  88.  
  89.      3.  File TECOC.H contains the "global"  definitions,  including  those
  90.          for most structures.
  91.  
  92.      4.  Variables  and  functions  are  defined  using   the   portability
  93.          identifiers  defined  in the ZPORT.H file.  Functions which do not
  94.          return a value are defined as VOID.   TECO-C  should  compile  and
  95.          link  on  different  machines  by  changing  only  the environment
  96.          definitions in the ZPORT.H file.
  97.  
  98.      5.  At one time, every function was in a file with the same  name
  99.          as  the  function.   This  made  it  easy  to  find the code for a
  100.          function.  The problem was that some groups of functions use  data
  101.          not  needed  by  the other functions.  This was especially true of
  102.          the system-dependent functions.  Also, some functions were  called
  103.          only by one other function, so it made sense for them to be in the
  104.          same module as the caller and be  made  "static".   So  now,  most
  105.          functions  are  in a file named the same as the function, with the
  106.          following exceptions:
  107.  
  108.          1.  All the "Z" functions are in are in the "Z" file for the given
  109.              system.
  110.  
  111.          2.  The conditionally-compiled functions (ZCpyBl in  ZINIT.C,  the
  112.              "Dbg" functions at the bottom of TECOC.C, the "v" functions in
  113.              EXEW.C) aren't in their own files.  If  they  were,  then  the
  114.              command procedures/makefiles that compile the files would need
  115.              to contain logic to conditionally compile the files.
  116.  
  117.                                                                 Page 3
  118.  
  119.  
  120.          3.  The functions for the "E" and "F" commands are in  EXEE.C  and
  121.              EXEF.C,  respectively.  So if you want to find function ExeEX,
  122.              don't look for a file named EXEEX.C.
  123.  
  124.  
  125.      6.  Symbols are 6 characters long or less.  The  way  I  remember  it,
  126.          this  was caused by the first system I wrote TECOC for:  CP/M-68k,
  127.          which had a limit of 8 characters for file names.   The  last  two
  128.          characters  had to be ".C", so 6 characters were left for the file
  129.          name.  Since the file  name  was  the  same  as  the  function  it
  130.          contained, functions were limited to 6 characters in length.  When
  131.          I saw how nicely the function declarations looked (they fit in one
  132.          tab slot), I used 6 characters for other symbols too.
  133.  
  134.          I've since been told that  CP/M-68k  has  8-character  file  names
  135.          followed  by  3-character file types, so CP/M-68k can't be blamed.
  136.          So shoot me.
  137.  
  138.          This standard has prevented problems from occurring with compilers
  139.          that don't support very many characters of uniqueness.
  140.  
  141.          In order to make up for the resultant  cryptic  names,  upper  and
  142.          lower  case  are mixed.  An uppercase letter indicates a new word.
  143.          For example, "EBfEnd" stands for "Edit Buffer End".  If  you  need
  144.          to  know what a variable name means, look at the definition of the
  145.          variable in DEFEXT.H.  The expanded  version  of  the  abbreviated
  146.          name  appears  in  the  comment  on  the same line as the variable
  147.          definition.   A  detailed  description  can  be  found  with   the
  148.          declaration of the variable in TECOC.C.
  149.  
  150.          The  limit  of  6  letters  in  variable  names  is   relaxed   in
  151.          system-dependent code.
  152.  
  153.      7.  Variable and function names follow patterns where  possible.   For
  154.          instance,  "EBfBeg"  and "EBfEnd" are the beginning and end of the
  155.          edit buffer.  If you see a variable named "BBfBeg", you can assume
  156.          that it is the beginning of some other buffer, and that a "BBfEnd"
  157.          exists which is the end of that buffer.
  158.  
  159.      8.  Character strings are usually represented in C by a pointer  to  a
  160.          sequences  of bytes terminated with a null character.  I didn't do
  161.          that in TECO-C because I thought it was too inefficient.   To  get
  162.          the  length  of  a  string,  you  have  to count characters.  Most
  163.          strings in TECO-C are therefore represented by two pointers, on to
  164.          the  first  character  and one to the character following the last
  165.          character.  With this representation, it's easy to add  characters
  166.          to a string and trivial to get the length.
  167.  
  168.      9.  Each file has a consistent format, which is:
  169.  
  170.          1.  a comment describing the function
  171.          2.  include directives
  172.          3.  the function declaration
  173.  
  174.                                                                 Page 4
  175.  
  176.  
  177.          4.  local variable definitions, in alphabetical order
  178.          5.  code
  179.  
  180.  
  181.  
  182.  
  183. 5  TOP LEVEL EXECUTION AND COMMAND PARSING
  184.  
  185.      The top level code for TECO-C is contained in  file  TECOC.C.   It  is
  186. very  simple:   after initializing, a loop is entered which reads a command
  187. string from the user, executes it, and loops back to read  another  command
  188. string.   If  the  user executes a command which causes TECO-C to exit, the
  189. program is exited directly via a call to the TAbort function.  TECO-C never
  190. exits by "falling out the bottom" of the main function.
  191.  
  192.      After a command string is read,  the  ExeCSt  function  is  called  to
  193. execute  the  command  string.  ExeCSt contains the top-level parsing code.
  194. The parse is trivial:  each command character is used as an  index  into  a
  195. table  of  functions.   The  table  contains  one entry for each of the 128
  196. possible characters.  Each function  is  responsible  for  "consuming"  its
  197. command  so  that when it returns, the command string pointer points to the
  198. next command.
  199.  
  200.  
  201.  
  202. 5.1  Error Handling
  203.  
  204.      When an error is detected, an error message is displayed at the  point
  205. that  the  error  is  detected,  and  the  function  in which the error was
  206. detected returns a FAILURE status to its caller.  Almost always, the caller
  207. returns  a FAILURE status to it's caller, which returns a FAILURE status to
  208. it's caller, etc.  When a FAILURE status is returned to  the  main  command
  209. string parser, parsing of the command string stops and the user is prompted
  210. for a new command string.
  211.  
  212.      This style tends to cause all function calls to follow the same  form,
  213. which is
  214.  
  215.                     if (function() == FAILURE)
  216.                             return(FAILURE);
  217.  
  218.      Things get more complicated in the system-dependent code (in the files
  219. with  names  that  start  with  a  "Z").  I extended TECO's error reporting
  220. slightly to allow the user to see the  operating  system's  reason  for  an
  221. error,  as this is often useful.  For example, under VAX/VMS there are many
  222. reasons why an attempt to create an output file might fail.  They  include:
  223. errors  in  file  name  syntax,  destination  directory non-existence, file
  224. protection violations or disk quota violation.  In order to  supply  enough
  225. information to the user, TECO-C outputs multiple-line error messages when a
  226. system error occurs.
  227.  
  228.      Multiple-line error messages  contain  one  line  that  describes  the
  229. operating  system's  perception  of  the error and one line that describe's
  230. TECO's perception of the error.  For instance, if a user of VAX/VMS does  a
  231. "EW[abc]test.txt$$"  command  when  the directory [abc] does not exist, the
  232.  
  233.                                                                 Page 5
  234.  
  235.  
  236. error message generated by TECO-C is:
  237.  
  238.             ?SYS   %RMS-F-DNF, directory not found
  239.             ?UFO   unable to open file "[abc]test.txt" for output
  240.  
  241.      System errors are therefore reported in  a  system-dependent  fashion,
  242. using  whatever  messages  the operating system can supply.  Under VAX/VMS,
  243. the system service $GETMSG provides human-readable messages that TECO-C can
  244. use  in the "SYS" part of the error message.  Under UNIX, syserrlist[error]
  245. is a pointer to these messages.
  246.  
  247.      There is another way in which error reporting in the  system-dependent
  248. code is tricky.  Under VAX/VMS, some system calls may return a code that is
  249. "successful" but contains extra information.  For instance, when a user has
  250. set his directories so that only a limited number of versions of a file can
  251. exist, RMS will automatically purge the oldest version of the file when the
  252. user  creates  a  file.   This only happens if the newly created file would
  253. cause too many versions of the file to exist.  When this happens,  the  VMS
  254. service  returns  a FILEPURGED status, which is successful.  TECO-C informs
  255. the user about these things by displaying the message in brackets.
  256.  
  257.  
  258.  
  259. 5.2  Command Modifiers (CmdMod)
  260.  
  261.      Command parsing  is  complicated  by  command  modifiers  and  numeric
  262. arguments, which may precede some commands.  These are implemented in a way
  263. that maintains the basic "jump table" idea.  For instance, when an  at-sign
  264. (@)  modifier  is  encountered  in  a  command  string, the at-sign command
  265. function (ExeAtS) is called.  The only thing ExeAtS  does  is  set  a  flag
  266. indicating  that  an  at-sign  has  been  encountered.   Commands which are
  267. affected by an at-sign modifier check this flag and behave accordingly.
  268.  
  269.      The flags which indicate command modifiers  are  contained  in  global
  270. variable  CmdMod.   A  bit in CmdMod is reserved for each command modifier.
  271. The modifiers are "@", ":" and "::".  Of course, once  the  flag  has  been
  272. set,  it  must be cleared.  With this parsing algorithm, the only way to do
  273. that is to make every command function explicitly  reset  CmdMod  before  a
  274. successful  return.  This is not too bad:  clearing all the flags in CmdMod
  275. is done with one statement:  "CmdMod = '\0';".
  276.  
  277.      For numeric arguments to commands, an expression stack  is  used  (see
  278. Stacks).   The  EstTop variable is the pointer to the top of the expression
  279. stack.  Commands which handle numeric arguments check EStTop to see if  the
  280. expression stack contains a value.
  281.  
  282.      A special case of  numeric  arguments  is  "m,n".   The  "m"  part  is
  283. encountered  and  causes  the value to be pushed onto the expression stack.
  284. The comma causes the ExeCom function to  move  the  value  into  a  special
  285. "m-argument"  global  variable (MArgmt), clear the expression stack and set
  286. another flag in CmdMod indicating that the "m" part of  an  "m,n"  pair  is
  287. defined.   Then the "n" is encountered and pushed onto the stack.  Commands
  288. which can take "m,n" pairs check the flag in CmdMod.
  289.  
  290.                                                                 Page 6
  291.  
  292.  
  293.      To summarize, CmdMod and  EStTop  are  variables  which  describe  the
  294. context  of  a command.  Each command function tests these variables to see
  295. if it was preceded by modifiers or  numbers.   For  this  to  work,  it  is
  296. important  that the expression stack and the flags in CmdMod are cleared at
  297. the right times.  It is the responsibility  of  each  command  function  to
  298. leave  CmdMod  and  EStTop  with  the  proper  values  before  successfully
  299. returning.  The rules are:
  300.  
  301.      1.  If the command function is returning FAILURE,  don't  worry  about
  302.          clearing  CmdMod  or EStTop.  They will be cleared before the next
  303.          command string is executed.
  304.  
  305.      2.  If the command function leaves a value on the expression stack, do
  306.          not  clear  EStTop before returning SUCCESS.  If the command calls
  307.          GetNmA,  do  not  clear  EStTop,  as  GetNmA  does  it  for   you.
  308.          Otherwise, clear EStTop before returning SUCCESS.
  309.  
  310.      3.  Clear CmdMod unless the command function sets flags  or  needs  to
  311.          leave  them alone.  ExeDgt, for example, handles digit strings and
  312.          doesn't clear CmdMod because the MARGIS bit may be set.
  313.  
  314.  
  315.  
  316.  
  317. 6  SEARCHING
  318.  
  319.      The search algorithm in TECO-C is complex.  The war between the desire
  320. for  a  fast search and the need to handle all the features of TECO'ssearch
  321. commands has produced code which can  be  a  real  pain  to  follow.   This
  322. section  attempts  to explain how things got the way they are.  The code is
  323. explained in a bottom-up fashion, to follow  the  way  it  evolved  in  the
  324. author's twisted mind.
  325.  
  326.      The basic search idea is to scan a contiguous edit buffer for a search
  327. string.  The steps are:
  328.  
  329.      1.  Search the edit buffer for  the  first  character  in  the  search
  330.          string.  If you reach the end of the edit buffer without matching,
  331.          the search fails.
  332.  
  333.      2.  When the first character of the search string matches a  character
  334.          in  the  edit  buffer,  try  to match successive characters in the
  335.          search string with the characters which follow the found character
  336.          in  the  edit buffer.  If they all match, the search succeeds.  If
  337.          one doesn't, go back to step 1.
  338.  
  339.  
  340.      This is basically what TECO-C does.  The  features  of  TECO's  search
  341. commands has buried these steps deep within some confusing code.
  342.  
  343.      The first complication is introduced by pattern  matching  characters.
  344. TECO  has  17 "match constructs", whiceh are indicated in the search string
  345. by the special characters ^X, ^S, ^N and ^Ex where "x" can be several other
  346. characters.   For  instance,  a  ^X  in  the  search  string means that any
  347. character is to be accepted as a match in  place  of  the  ^X.   Characters
  348.  
  349.                                                                 Page 7
  350.  
  351.  
  352. other  than  the  match  constructs represent themselves.  An example:  the
  353. search string "a^Xb" contains 3 match constructs:  a, ^X and b.
  354.  
  355.      TECO also supports forward  or  backward  searching.   When  searching
  356. backwards,  only  the  search  for  the first match construct in the search
  357. string is done in a backwards direction.  When the character is found,  the
  358. characters  following  it  are  compared in a forward direction to the edit
  359. buffer characters.  This means that once the first match construct has been
  360. found,  a single piece of code can be used to compare successive characters
  361. in the search  string  with  successive  characters  in  the  edit  buffer,
  362. regardless of whether the search is forwards or backwards.
  363.  
  364.      Adding these new features, the new description of searching is:
  365.  
  366.      1.  Search the edit buffer forwards or backwards for a character which
  367.          matches  the  first  match construct in the search string.  If you
  368.          reach the end of the edit  buffer  without  matching,  the  search
  369.          fails.
  370.  
  371.      2.  When the first match construct of  the  search  string  matches  a
  372.          character  in  the  edit  buffer,  try  to  match successive match
  373.          constructs in the search string with the characters  which  follow
  374.          the  found  character  in the edit buffer.  If they all match, the
  375.          search succeeds.  If one doesn't, go back to step 1.
  376.  
  377.  
  378.      To begin a description of which routines implement  the  above  steps,
  379. and  in  order  to  have  a  reference  for later discussion, the following
  380. hierarchy chart of "who calls who" is presented.
  381.  
  382.  
  383.  
  384.                                                                 Page 8
  385.  
  386.  
  387.  ExeEUn ExeFB ExeFC ExeFD ExeFK ExeFN ExeFS ExeFUn ExeN ExeS ExeUnd
  388.     |     |     |     |     |     |     |     |      |    |    |
  389.     |     |     |     |     |     |     |     |      |    |    |
  390.     ------------------------------------------------------------
  391.                                   |
  392.                                   V
  393.                                 Search
  394.                                   |
  395.                                   V
  396.                                 SrcLop
  397.                                   |
  398.                                   V
  399.                                 SSerch
  400.                                |  |  |
  401.                         +------+  |  +------+
  402.                  +---+  |         |         |  +---+
  403.                  |   V  V         |         V  V   |
  404.                  |  ZFrSrc        |        BakSrc  |
  405.                  |   |  |         |         |  |   |
  406.                  +---+  |         |         |  +---+
  407.                         +------+  |  +------+
  408.                                V  V  V
  409.                                 CMatch  <--+
  410.                                   |        |
  411.                                   +--------+
  412.  
  413.  
  414.      At the top are the functions that implement search commands  (E_,  FB,
  415. FC,  FD, FK, FN, FS, F_, N, S and _).  All of these functions call the main
  416. search function:  Search.
  417.  
  418.      At the lower level are the functions which implement  steps  1  and  2
  419. described   above.   ZFrSrc  searches  forwards  in  the  edit  buffer  for
  420. characters which match the first character in the  search  string.   BakSrc
  421. does the same thing, but searches backwards.  SSerch calls one of these two
  422. functions and then executes a loop which calls CMatch to compare successive
  423. match  constructs  in  the  search string to characters following the found
  424. character in the edit buffer.  The reason that ZFrSrc,  BakSrc  and  CMatch
  425. call themselves is to handle some of the more esoteric match constructs.
  426.  
  427.      Case dependence in TECO is controlled by the search mode flag (see the
  428. ^X  command).  The variable SMFlag holds the value of the search mode flag,
  429. and is used by ZFrSrc, BakSrc and CMatch.
  430.  
  431.      One final point to help confuse things:  ZFrSrc  is  system-dependent.
  432. It  contains  a  VAX/VMS-specific version which uses the LIB$SCANC run-time
  433. library routine to access the SCANC  instruction.   The  SCANC  instruction
  434. looks  like  it was designed to handle TECO's match constructs.  I couldn't
  435. resist using it, but it was a mistake,  as  it  needlessly  complicates  an
  436. already  messy  algorithm.   I have decided to remove the VMS-specific code
  437. some time in the future.
  438.  
  439.      Further complications of the search algorithm  arise  because  of  the
  440. following capabilities of TECO searches:
  441.  
  442.                                                                 Page 9
  443.  
  444.  
  445.      1.  If there is no text argument, use the previous search argument.
  446.  
  447.      2.  If colon modified, return success/failure and no error message
  448.  
  449.      3.  If the search fails and we're in a loop and  a  semicolon  follows
  450.          the  search  command,  exit  the  loop without displaying an error
  451.          message.
  452.  
  453.      4.  Handle optional repeat counts
  454.  
  455.      5.  If the ES flag is non-zero, verify the search based on  the  value
  456.          of the flag.
  457.  
  458.      6.  If bit 64 of the ED flag is set,  move  dot  by  one  on  multiple
  459.          searches.
  460.  
  461.      7.  If bit 16 of the ED flag  is  set,  don't  move  after  a  failing
  462.          search.
  463.  
  464.      8.  Be fast.
  465.  
  466.  
  467.  
  468.  
  469. 7  MEMORY MANAGEMENT
  470.  
  471.      7.1  The Edit Buffer And Input Buffer
  472.  
  473.      TECO-C is based on TECO-11, but it  uses  a  different  form  of  edit
  474. buffer memory management.  Here's why.
  475.  
  476.      The edit buffer in TECO-11 is implemented as  a  continuous  block  of
  477. memory.   This  allows  rapid  movement  through  the  edit buffer (by just
  478. maintaining a  pointer  to  the  current  spot)  and  makes  searches  very
  479. straightforward.  Insertion and deletion of text is expensive, because each
  480. insertion or deletion requires moving the text following the spot where the
  481. insertion  or  deletion  occurs  in order to maintain a continuous block of
  482. memory.  This gets to be a real pain when a  video  editing  capability  is
  483. added to TECO, because in video mode text is added/deleted one character at
  484. a time very rapidly.
  485.  
  486.      TECO-C uses a edit buffer gap scheme.   The  edit  buffer  occupies  a
  487. continuous piece of memory, but there is a gap at the "current spot" in the
  488. edit buffer.  When the user moves around the edit buffer, the gap is  moved
  489. by  shuffling  text from one side of the gap to the other.  This means that
  490. moving around the text buffer is slower than for TECO-11's scheme, but text
  491. insertion  and deletion is very fast.  Searches are still fast because most
  492. searches start at the current spot and  go  forwards  or  backwards,  so  a
  493. continuous  piece  of memory is searched.  In the future, when some kind of
  494. video mode is added, insertion and deletion one-character-at-a-time will be
  495. fast using the gap scheme.
  496.  
  497.      The variables that maintain pointers to the edit buffer  and  the  gap
  498. within  the buffer can be confusing, so here's some examples.  Suppose that
  499. 10000 bytes are allocated for the edit buffer when TECO-C  is  initialized.
  500.  
  501.                                                                Page 10
  502.  
  503.  
  504. Suppose the allocated memory starts at address 3000.
  505.  
  506.         Empty edit buffer (the gap spans the whole edit buffer):
  507.  
  508.                 EBfBeg = 3000           (edit buffer beginning)
  509.                 GapBeg = 3000           (gap beginning)
  510.                 GapEnd = 13000          (gap end)
  511.                 EBfEnd = 13000          (edit buffer end)
  512.  
  513.         Buffer contains "test",  character pointer is before the first 't':
  514.  
  515.                 EBfBeg = 3000           (edit buffer beginning)
  516.                 GapBeg = 3000           (gap beginning)
  517.                 GapEnd = 12996          (gap end)
  518.                          12997  't'
  519.                          12998  'e'
  520.                          12999  's'
  521.                 EBfEnd = 13000  't'     (edit buffer end)
  522.  
  523.  
  524.         Buffer contains "test",  character pointer is after the last 't':
  525.  
  526.                 EBfBeg = 3000   't'     (edit buffer beginning)
  527.                          3001   'e'
  528.                          3002   's'
  529.                          3003   't'
  530.                 GapBeg = 3004           (gap beginning)
  531.                 GapEnd = 13000          (gap end)
  532.                 EBfEnd = 13000          (edit buffer end)
  533.  
  534.  
  535.         Buffer contains "test",  character pointer is after the 'e':
  536.  
  537.                 EBfBeg = 3000   't'     (edit buffer beginning)
  538.                          3001   'e'
  539.                 GapBeg = 3002           (gap beginning)
  540.                 GapEnd = 12998          (gap end)
  541.                          12999  's'
  542.                 EBfEnd = 13000  't'     (edit buffer end)
  543.  
  544.      When an insertion command is executed, the text is  inserted  starting
  545. at  GapBeg.  When a deletion command is executed, GapEnd is incremented for
  546. a forward delete or GapBeg is decremented for a backwards delete.  When the
  547. character  pointer  is moved forwards, the gap is moved forwards by copying
  548. text from the end of the gap to the beginning.  When the character  pointer
  549. is moved backwards, the gap is moved backwards by copying text from the the
  550. area just before the gap to the area at the end of the gap.
  551.  
  552.      There are a few messy cases, such as when a bounded search is executed
  553. and  the bounded text area includes the edit buffer gap.  In this case, the
  554. gap is temporarily moved so that the search can proceed over  a  continuous
  555. memory area.
  556.  
  557.                                                                Page 11
  558.  
  559.  
  560.      In order to confuse things a little, TECO-C has one  addition  to  the
  561. basic  edit  buffer  gap  management.  Following the end of the edit buffer
  562. (EBfEnd) is the current input stream buffer.   Since  file  input  commands
  563. always  cause  text  to  be appended to the end of the edit buffer, this is
  564. natural.  Thus, no input buffer is needed:  text is input directly into the
  565. edit  buffer.   This  makes  the code a little confusing, but it avoids the
  566. problem of having an input buffer.  When you have an input buffer, you have
  567. to  deal with the question of how large the buffer should be and what to do
  568. with it when it's too small.  this  scheme  is  fast  and  and  saves  some
  569. memory.  (see File Input)
  570.  
  571.  
  572.  
  573. 7.2  Q-registers
  574.  
  575.      Q-registers have two parts:  a numeric part and  a  text  part.   Each
  576. q-register  is  represented by a structure containing three fields:  one to
  577. hold the numeric part and two to point to the  beginning  and  end  of  the
  578. memory holding the text part.  If the text part of the q-register is empty,
  579. then the pointer to the beginning of the text is NULL.
  580.  
  581.      There are 36 global q-registers, one for each letter of  the  alphabet
  582. and  1  for  each digit from 0 to 9.  These q-registers are accessible from
  583. any macro level.  There are 36 local q-registers for each macro level.  The
  584. names  for  local  q-registers  are preceded by a period.  Thus the command
  585. "1xa" inserts a line into global q-register "a", while the  command  "1x.a"
  586. inserts  a line into local q-register ".a".  Storage for the data structure
  587. defining local q-registers is not allocated until  a  local  q-register  is
  588. first  used.   This  saves  space  and  time, because local q-registers are
  589. rarely used, and doing things this way avoids allocating and freeing memory
  590. every time a macro is executed.
  591.  
  592.  
  593.  
  594. 8  STACKS
  595.  
  596.      8.1  Expression Stack
  597.  
  598.      An expression stack is used to parse TECO's expressions.  Consider the
  599. command string QA+50=$$.  When the command string is executed, the value of
  600. QA is pushed on the expression stack, then the operator "+"  is  pushed  on
  601. the  expression  stack, and then the value "50" is pushed on the expression
  602. stack.  Whenever a full expression that can be reduced is on the expression
  603. stack, it is reduced.  For the above example, the stack is reduced when the
  604. value "50" is pushed.
  605.  
  606.      The expression stack is implemented in the following variables:
  607.  
  608.         EStack  the stack itself,  containing saved operators and operands
  609.         EStTop  index of the top element in EStack
  610.         EStBot  index of the current "bottom" of the stack in EStack
  611.  
  612.      The "bottom" of the expression stack can change because an  expression
  613. can  include  a macro invocation.  For example, the command QA+M3=$$ causes
  614. the value of "QA" to be pushed on the expression stack,  then  the  "+"  is
  615.  
  616.                                                                Page 12
  617.  
  618.  
  619. pushed,  and  then  the  macro  contained in q-register 3 is executed.  The
  620. macro in q-register 3 returns a value to be used in the  expression.   When
  621. the macro is entered, a new expression stack "bottom" is established.  This
  622. allows  the  macro  to  have  a  "local"  expression  stack  bottom   while
  623. maintaining the stack outside the macro.
  624.  
  625.  
  626.  
  627. 8.2  Loop Stack
  628.  
  629.      The loop stack contains the loop count and the address  of  the  first
  630. command  in  the loop.  For example, in the command 5<FSMP$mt$>$$, the loop
  631. stack contains the loop count (5) and the address of the first  command  in
  632. the  loop  (F).  Whenever the end-of-loop character (>) is encountered, the
  633. loop count is decremented.  If the loop count is still  greater  than  zero
  634. after  it has been decremented, then the command string pointer is reset to
  635. point to the first character in the loop (F).
  636.  
  637.      The loop stack is implemented in the following variables:
  638.  
  639.         LStack  the stack itself,  containing saved counts and addresses
  640.         LStTop  index of the top element in LStack
  641.         LStBot  index of the current "bottom" of the stack in LStack
  642.  
  643.      The loop stack needs a "floating" bottom for the same reason that  the
  644. expression   stack   needs  one:   macros.   Consider  the  command  string
  645. 4<Smp$M7$>$$.  When the "<" in is encountered, the loop count (4)  and  the
  646. address  of  the  first  character  in  the loop (S) are placed on the loop
  647. stack.  Command execution continues, and the "M7" command  is  encountered.
  648. Suppose  that  q-register 7 contains the erroneous command string 10>DL>$$.
  649. When the ">" command is encountered in the macro,  TECO  expects  the  loop
  650. stack to contain a loop count and an address for the first character in the
  651. loop.  In this example, there is no matching "<" command in the macro which
  652. would  have  set  up  the loop stack.  It would be very bad if TECO were to
  653. think that the loop count was 4 and the first command in the loop was  "S".
  654. In this situation, what TECO should do is generate the error message "BNI >
  655. not in iteration".  In order to implement  this,  the  variable  LStBot  is
  656. adjusted  each  time  a  macro is entered or exited.  LStBot represents the
  657. bottom of the loop stack for the current macro level.
  658.  
  659.  
  660.  
  661. 8.3  Macro Stack
  662.  
  663.      The macro stack is used to preserve  context  each  time  a  macro  is
  664. entered.   All important values are pushed onto the stack before a macro is
  665. entered and popped off the stack when the macro is exited.  The macro stack
  666. is  also  used  by  the  EI  command,  which means it's used when executing
  667. initialization files and mung files.
  668.  
  669.  
  670.  
  671. 9  HELP
  672.  
  673.      This section discusses on-line HELP, which  is  available  only  under
  674.  
  675.                                                                Page 13
  676.  
  677.  
  678. VAX/VMS.
  679.  
  680.      The HELP command is not documented in the TECO manual  distributed  by
  681. DEC.,  even  though  it  is supported in TECO-11 and TECO-32.  To get help,
  682. simply type "HELP" followed by a carriage return.  HELP is  the  only  TECO
  683. command that is not terminated by double escapes.
  684.  
  685.      Help  in  TECOC  is  different  than  help  in  TECO-11.   In  TECO-C,
  686. interactive  help mode is entered, so that a user can browse through a help
  687. tree, as he can from DCL.  In  TECO-C,  access  is  provided  to  only  two
  688. libraries:   the  library  specific  to  TECO-C (pointed to by logical name
  689. TEC$INIT) and the system help library.  To get help  on  TECO-C,  just  say
  690. "HELP",  with  or  without arguments.  To get help from the system library,
  691. say "HELP/S".  I find this easier to use than TECO-11's syntax.
  692.  
  693.      The help library for TECO-C is contained in file TECOC.HLB,  which  is
  694. generated  from  TECOC.HLP,  which  is  generated from TECOC.RNH.  See file
  695. TECOC.RNH for a description of how to do it.   This  help  library  is  far
  696. broader  than  the library for TECO-11, but much of it has yet to be filled
  697. in.
  698.  
  699.      The help library is also the repository for  verbose  error  messages,
  700. which are displayed when the help flag (EH) is set to 3.  For systems other
  701. than VMS, the ZHelp function displays  verbose  text  contained  in  static
  702. memory (see file ZHELP.C).
  703.  
  704.  
  705.  
  706. 10  FILE INPUT
  707.  
  708.      TECO has an elegant design that allows high speed input.  There are no
  709. linked  list  data  structures  to  keep track of, and most file input goes
  710. directly to the end of the edit buffer.
  711.  
  712.      TECO-C takes advantage of this by reading normal file  input  directly
  713. to  the end of the edit buffer.  After each input call, nothing needs to be
  714. moved; the pointer to the end of the edit  buffer  is  simply  adjusted  to
  715. point  to  the  end  of the new record.  The pointer to the end of the edit
  716. buffer (EBfEnd) serves two purposes:  it points to  the  end  of  the  edit
  717. buffer and to the beginning of the input buffer.
  718.  
  719.      A side effect of this scheme is the sharing of memory between the edit
  720. buffer and the input buffer.  When the edit buffer is empty, it can be made
  721. smaller by shrinking the edit buffer gap in order to make the input  buffer
  722. larger.   Obviously,  if  the  edit  buffer needs to be expanded, the input
  723. buffer can suffer  before  more  memory  is  actually  requested  from  the
  724. operating  system.   This  is  easily achieved by moving the pointer to the
  725. "end-of-the-edit-buffer"/ "beginning-of-the-input-buffer".
  726.  
  727.      This scheme works, but provides no support for the other forms of file
  728. input.   The  EP and ER$ commands provide a complete secondary input stream
  729. which can be open at the same time as the primary stream (two  input  files
  730. at  once).   The  EI  command  reads  and  executes  files  containing TECO
  731. commands, and is used to execute the initialization file,  if  one  exists.
  732. The  EQq  command,  if  implemented,  reads  the  entire contents of a file
  733.  
  734.                                                                Page 14
  735.  
  736.  
  737. directly into a Q-register.
  738.  
  739.      A second problem arises:  on each of the open files, the quantum  unit
  740. of  input  is  not  standard.   For  A,  Y  and  P commands, a form feed or
  741. end-of-file "terminate" the read.  For n:A commands, form feed, end-of-line
  742. or  end-of-file  "terminate"  each  read.   For EI commands, two escapes or
  743. end-of-file "terminate" the read.  The input code must "save"  the  portion
  744. of  an  input record following a special character and yield the saved text
  745. when the next command for the file is executed.
  746.  
  747.      The scheme used in TECO-C is to  read  text  from  the  current  input
  748. stream  directly  to  the end of the edit buffer.  When the input stream is
  749. switched via a EP or ER$ command, the obvious switching of file descriptors
  750. happens,  and  any  text that's "leftover" from the last read is explicitly
  751. saved elsewhere.  Note that this happens VERY rarely, so a  malloc/free  is
  752. acceptable.
  753.  
  754.      For EI and EQq commands, the input memory following the edit buffer is
  755. used  as  a  temporary  input  buffer.  After the file is read, the text is
  756. copied to a Q-register in the case of EQq and to a separate buffer  in  the
  757. case of EI.
  758.  
  759.  
  760.  
  761. 11  VIDEO
  762.  
  763.      As of 18-Feb-1991, TECO-C supports video only under  Unix.   The  code
  764. was  written  by  Mark  Henderson,  using  the  CURSES  package.   See file
  765. VIDEO.TXT for a discussion of how it works.
  766.  
  767.  
  768.  
  769. 12  PORTABILITY
  770.  
  771.      TECO-C was written with portability in mind.   The  first  development
  772. machine  was  "minimal":   a  SAGE  IV  (68000)  running CP/M-68k.  In that
  773. environment, there was no "make" utility.
  774.  
  775.      Initially, the system-independent code (files that don't start with  a
  776. "Z")  had  absolutely  no  calls to standard C runtime functions.  This was
  777. because I had several problems with  the  "standard"  functions  not  being
  778. "standard" on different machines.  With the onset of ANSI C I've grown less
  779. timid, but the main code still references  almost  no  standard  functions.
  780. This  is  less  of  a  limitation than you might think:  TECO-C doesn't use
  781. null-terminated strings.  It also doesn't use unions, floating point or bit
  782. fields.
  783.  
  784.  
  785.  
  786. 13  PORTING TO A NEW ENVIRONMENT
  787.  
  788.  
  789.      1.  Move the source code to the target machine.
  790.  
  791.                                                                Page 15
  792.  
  793.  
  794.      2.  Inspect file ZPORT.H.  You need to select the  compiler  you  want
  795.          the code compiled for.  For instance, if you are porting to a Unix
  796.          system, then fix ZPORT.H so that the unix  identifier  is  defined
  797.          (it  is  usually  defined  by  default  by the compiler).  If your
  798.          compiler is nothing like anything supported by ZPORT.H,  then  set
  799.          the UNKNOWN identifier.
  800.  
  801.      3.  Compile and link.  See file AAREADME.TXT for descriptions  of  how
  802.          TECO-C  is  built  in  supported environments, and steal like mad.
  803.          The problem here is that you need a "Z" file for your environment,
  804.          containing  all  the  "Z" functions needed by TECO-C.  The easiest
  805.          thing to do is copy ZUNKN.C to your own "Z" file and link  against
  806.          that.   For  instance,  if I ever port TECO-C to a Macintosh, I'll
  807.          copy ZUNKN.C to ZMAC.C.
  808.  
  809.      4.  Fix things  so  the  compile/link  is  successful.   If  you  have
  810.          compiled  with UNKNOWN set, you should get an executable file that
  811.          displays a  message  and  dies  when  the  first  system-dependent
  812.          function  is  called.  The strategy is to fix that function (often
  813.          by stealing from the code for other operating systems), relink and
  814.          deal  with  the  next message until you have something that works.
  815.          Functions should be implemented in roughly  the  following  order:
  816.          ZInit,  ZTrmnl, ZExit, ZDspCh, ZAlloc, ZRaloc, ZFree, ZChin.  This
  817.          will give you a TECO with everything but file I/O.   You  can  run
  818.          it,  add  text  to  the  edit  buffer,  delete  text,  search, use
  819.          expressions and the = sign command (a calculator).  Then  do  file
  820.          input:   ZOpInp,  ZRdLin,  ZIClos.   Then do file output:  ZOpout,
  821.          ZWrBfr, ZOClos, ZOClDe.  Use the test macros (*tst*.tec)  to  test
  822.          how everything works (see Testing).
  823.  
  824.  
  825.  
  826.  
  827. 14  TESTING
  828.  
  829.      Testing of TECO-C is performed by executing macros.   The  macros  are
  830. contained  in  files named TSTxxx.TEC, where XXX is some kind of indication
  831. as to what is tested.  For instance, TSTQR.TEC tests q-registers.  The test
  832. macros  do  not  test  all  the  functions  provided  by  TECO.   They were
  833. originally used to verify that TECO-C performs exactly the same as  TECO-11
  834. under  the  VMS operating system.  When I needed to test a chunk of code, I
  835. sometimes did it the right way and wrote a macro.
  836.  
  837.  
  838.  
  839. 15  DEBUGGING
  840.  
  841.      A debugging system (very ugly, very useful)  is  imbedded  within  the
  842. code.   It  is conditionally complied into the code by turning on or off an
  843. identifier (DEBUGGING) defined in the TECOC.H file.  When debugging code is
  844. compiled  in,  you can access it using the ^P command, which is not used by
  845. regular TECO.  The ^P command with no argument will display help about  how
  846. to use ^P.
  847.  
  848.                                                                Page 16
  849.  
  850.  
  851.      If you are working under  VMS,  it  sometimes  helps  to  compare  the
  852. execution  of  TECO-C with TECO-11.  Put a test command string into a file.
  853. Use DEFINE/USER_MODE to redirect the output of TECO-C to a file and execute
  854. the  macro  with  TECO-C.   Then  do  the same thing with TECO-11.  Use the
  855. DIFFERENCES command to compare the two output files.  They  should  be  100
  856. percent identical.
  857.